<html>
<head><meta charset="utf-8"><title>environment, locking, fork, and Command · t-libs · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/index.html">t-libs</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html">environment, locking, fork, and Command</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="229219925"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229219925" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229219925">(Mar 07 2021 at 21:39)</a>:</h4>
<p>If I recall correctly, all this unfortunate business with env lock is related to the fact that Command wants to use a new environment configured for child for PATH lookup.</p>



<a name="229220049"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229220049" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229220049">(Mar 07 2021 at 21:41)</a>:</h4>
<p>but maybe it should just make a copy as suggested earlier</p>



<a name="229222799"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229222799" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229222799">(Mar 07 2021 at 22:23)</a>:</h4>
<p>Is it required to do the PATH-search itself? Couldn't it just fork the child, change the environment as directed in the child, and <em>then</em> do the PATH lookup (or call <code>execvpe</code>)?</p>



<a name="229222874"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229222874" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229222874">(Mar 07 2021 at 22:24)</a>:</h4>
<p>That wouldn't even require making a copy.</p>



<a name="229222976"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229222976" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229222976">(Mar 07 2021 at 22:26)</a>:</h4>
<p>Another thread could be changing the environment at that time, which is why I would expect a copy to be necessary.</p>



<a name="229223009"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229223009" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229223009">(Mar 07 2021 at 22:27)</a>:</h4>
<p>Are you concerned about the changes taking effect, or are you concerned about the environment being in an inconsistent state when <code>fork</code> snapshots it for the child?</p>



<a name="229223014"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229223014" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229223014">(Mar 07 2021 at 22:27)</a>:</h4>
<p>About an inconsistent state.</p>



<a name="229223196"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229223196" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229223196">(Mar 07 2021 at 22:30)</a>:</h4>
<p>I'm assuming you're concerned about another thread using the Rust environment functions, rather than another thread calling <code>setenv</code> directly (since the raw C function isn't necessarily thread-safe in the first place)?</p>



<a name="229223436"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229223436" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229223436">(Mar 07 2021 at 22:34)</a>:</h4>
<p>(As a side note, glibc's setenv actually does seem to be thread-safe.)</p>



<a name="229224273"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229224273" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229224273">(Mar 07 2021 at 22:49)</a>:</h4>
<p>Modification through Rust library functions, concurrently from another threads, is what I had in mind, yes.</p>



<a name="229224352"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229224352" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229224352">(Mar 07 2021 at 22:50)</a>:</h4>
<p>I'm currently writing a patch to the exec manpage, because I found a corner case it didn't explain and had to dig into the source code. (Turns out that <code>execvpe</code> searches the caller's <code>PATH</code>, <em>not</em> the path supplied as an argument.)</p>



<a name="229225077"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225077" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225077">(Mar 07 2021 at 23:02)</a>:</h4>
<p>Yeah, that is one of reasons why I find Rust behaviour surprising. Though, if I recall correctly, there are no functions in POSIX that use PATH and custom environment both.</p>



<a name="229225094"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225094" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225094">(Mar 07 2021 at 23:02)</a>:</h4>
<p>Yeah, <code>execvpe</code> is apparently an extension.</p>



<a name="229225344"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225344" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225344">(Mar 07 2021 at 23:07)</a>:</h4>
<p>OK. So, one way to solve this would be for Rust to snapshot the Rust environment completely, then fork, then set that environment in the child. That would <em>work</em>, but it seems like an excessive amount of overhead to impose on process spawning.</p>



<a name="229225487"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225487" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225487">(Mar 07 2021 at 23:09)</a>:</h4>
<p>I think I'm going to split discussion of alternative fixes out of this CI-fixing thread.</p>



<a name="229225573"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225573" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Notification Bot <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225573">(Mar 07 2021 at 23:10)</a>:</h4>
<p>This topic was moved here from <a class="stream-topic" data-stream-id="242791" href="/#narrow/stream/242791-t-infra/topic/i686-gnu.20timeouts">#t-infra &gt; i686-gnu timeouts</a> by <span class="user-mention silent" data-user-id="239881">Josh Triplett</span></p>



<a name="229225644"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225644" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225644">(Mar 07 2021 at 23:11)</a>:</h4>
<p>(Context for t-libs: this grew out of the linked discussion about CI failures, which are being fixed for the moment with a revert. This part of the discussion is about whether there's a better long-term fix for environment handling around Command.)</p>



<a name="229225897"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229225897" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229225897">(Mar 07 2021 at 23:15)</a>:</h4>
<p>In theory, we could take over environment handling ourselves, and point <code>environ</code> to point to memory we own, whenever we want to change the environment. That would mean we know anything <em>other</em> than ourselves will have to change <code>environ</code> if it wants to change the environment in ways that might lead to inconsistency, and we can handle the environment in a safe way where we know "our" last environment value, which means we could potentially do an atomic snapshot of <code>environ</code> and then check in the child if that snapshot is still valid. That would have many downsides, though, apart from complexity. Any use of libc to change the environment would result in copying the entire environment, which would add overhead to simple <code>setenv</code> operations from C.</p>



<a name="229226074"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229226074" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229226074">(Mar 07 2021 at 23:18)</a>:</h4>
<p>Assuming we don't want to do that, which I don't think we do, that means we're stuck with libc's environment handling.</p>



<a name="229226107"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229226107" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229226107">(Mar 07 2021 at 23:19)</a>:</h4>
<p>If we can address the issue of <code>fork</code>, for everything else we could make our own environment handling more target-aware; specifically, we could know that on glibc targets, glibc's environment handling already does its own internal locking, which means we don't need to do our own. That doesn't address <code>fork</code> though.</p>



<a name="229228030"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229228030" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Eric Huss <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229228030">(Mar 07 2021 at 23:49)</a>:</h4>
<p>I think the current approach is not unreasonable.  Just need to change it so it doesn't attempt to unlock the lock after <code>fork</code>. </p>
<p>Even though glibc may have a lock on <code>setenv</code>, it is still documented as mt-unsafe.  I would be uncomfortable making any assumptions there.</p>
<p>There was recently a discussion on internals about the mess around <code>setenv</code> here: <a href="https://internals.rust-lang.org/t/function-to-hold-lock-on-execution-environment-for-ffi/13702">https://internals.rust-lang.org/t/function-to-hold-lock-on-execution-environment-for-ffi/13702</a></p>



<a name="229228402"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229228402" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229228402">(Mar 07 2021 at 23:55)</a>:</h4>
<p>Hmmm. Just not unlocking the lock <em>might</em> be an option, iff it's acceptable to be unable to touch the environment in a <code>before_exec</code>/<code>pre_exec</code> function.</p>



<a name="229228492"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229228492" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229228492">(Mar 07 2021 at 23:56)</a>:</h4>
<p>That raises another possibility: if we change how we store the lock a little, we could reinitialize the lock immediately after <code>fork</code>.</p>



<a name="229228571"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229228571" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229228571">(Mar 07 2021 at 23:57)</a>:</h4>
<p>We could make that change, starting with the now-reverted-to-mutex code, and then re-apply the change to switch to an rwlock.</p>



<a name="229228757"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229228757" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229228757">(Mar 08 2021 at 00:00)</a>:</h4>
<p>Does that seem reasonable? Release the lock in the parent process, reinitialize the lock (without ever touching the original again even to unlock it) in the child?</p>



<a name="229235125"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229235125" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229235125">(Mar 08 2021 at 01:37)</a>:</h4>
<p>I vaguely remember messing with setenv &amp; fork a while ago. Can't remember the context though.</p>



<a name="229235205"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229235205" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229235205">(Mar 08 2021 at 01:38)</a>:</h4>
<p>Locking in the parent before forking and then unlocking in both the parent and child is generally the correct way to do this.</p>



<a name="229235213"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229235213" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229235213">(Mar 08 2021 at 01:38)</a>:</h4>
<p>You don't need to mess with manually resetting the lock in the child.</p>



<a name="229235237"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229235237" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229235237">(Mar 08 2021 at 01:39)</a>:</h4>
<p>Hmm, actually you might.</p>



<a name="229235255"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229235255" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229235255">(Mar 08 2021 at 01:39)</a>:</h4>
<p>You're not actually allowed to call any pthread functions in the child.</p>



<a name="229259827"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229259827" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229259827">(Mar 08 2021 at 07:55)</a>:</h4>
<p>Yeah, I don't think it's correct to unlock in the child with either kind of mutex.</p>



<a name="229259993"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229259993" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229259993">(Mar 08 2021 at 07:57)</a>:</h4>
<p>And on top of that, many of the pthread functions (including the mutex functions) aren't async-signal-safe, so they can't be called after fork and before exec.</p>



<a name="229280299"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229280299" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229280299">(Mar 08 2021 at 10:58)</a>:</h4>
<blockquote>
<p>iff it's acceptable to be unable to touch the environment in a before_exec/pre_exec function.</p>
</blockquote>
<p>is setenv even allowed after fork?</p>



<a name="229282496"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229282496" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229282496">(Mar 08 2021 at 11:16)</a>:</h4>
<p>No</p>



<a name="229283172"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229283172" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229283172">(Mar 08 2021 at 11:23)</a>:</h4>
<p>It depends? The single threaded programs would be one of things to consider.</p>



<a name="229288188"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229288188" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Steven Fackler <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229288188">(Mar 08 2021 at 12:09)</a>:</h4>
<blockquote>
<p>After a fork() in a multithreaded program, the child can safely call only async-signal-safe functions (see signal-safety(7)) until such time as it calls execve(2).</p>
</blockquote>



<a name="229345496"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229345496" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229345496">(Mar 08 2021 at 18:02)</a>:</h4>
<p>Many, <em>many</em> programs do setenv after fork and before exec, to set up the child's environment. But yeah, in theory any such program that's multithreaded <em>could</em> fail if another thread happened to be in the midst of a setenv, or for that matter a malloc if setenv wants to change the allocation...</p>



<a name="229346165"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229346165" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229346165">(Mar 08 2021 at 18:07)</a>:</h4>
<p>Ah, I see; in Rust, the child process just sets <code>environ</code>, it doesn't call setenv.</p>



<a name="229346190"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229346190" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229346190">(Mar 08 2021 at 18:07)</a>:</h4>
<p>That can be done without a race.</p>



<a name="229346451"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229346451" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229346451">(Mar 08 2021 at 18:09)</a>:</h4>
<p>OK, perhaps we <em>do</em> need to just copy the environment (if we need to change it). And prepare the changed environment in the parent, too, since we can't malloc. And then document that pre_exec functions can't affect the environment...</p>



<a name="229363844"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229363844" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229363844">(Mar 08 2021 at 19:54)</a>:</h4>
<p>I posted a complete summary to <a href="https://github.com/rust-lang/rust/issues/64718#issuecomment-793030479">https://github.com/rust-lang/rust/issues/64718#issuecomment-793030479</a> . Gah, this is a mess.</p>



<a name="229366036"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229366036" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229366036">(Mar 08 2021 at 20:10)</a>:</h4>
<p><code>posix_spawnp</code> is never used when PATH had been modified and lookup is required.</p>



<a name="229366619"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229366619" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tm <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229366619">(Mar 08 2021 at 20:14)</a>:</h4>
<p>Another thing that came up in previous attempts to implement path search on Rust side, was that there are platform specific defaults when PATH is unset.</p>



<a name="229371412"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229371412" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229371412">(Mar 08 2021 at 20:51)</a>:</h4>
<p><span class="user-mention silent" data-user-id="352985">tm</span> <a href="#narrow/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command/near/229366036">said</a>:</p>
<blockquote>
<p><code>posix_spawnp</code> is never used when PATH had been modified and lookup is required.</p>
</blockquote>
<p>Ah, I didn't catch that. But if we have our own <code>PATH</code> search code, we could drop all that logic and call <code>posix_spawn</code> in more cases.</p>



<a name="229371663"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229371663" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229371663">(Mar 08 2021 at 20:53)</a>:</h4>
<p><span class="user-mention silent" data-user-id="352985">tm</span> <a href="#narrow/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command/near/229366619">said</a>:</p>
<blockquote>
<p>Another thing that came up in previous attempts to implement path search on Rust side, was that there are platform specific defaults when PATH is unset.</p>
</blockquote>
<p>I'm aware, but I think we might still be able to fix that. (Worst case, we might have to propagate those defaults, but I suspect in practice it might be viable to ignore those for consistency.)</p>



<a name="229551197"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229551197" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229551197">(Mar 09 2021 at 20:49)</a>:</h4>
<p>PR for the first two points of your summary. <a href="https://github.com/rust-lang/rust/issues/82949">#82949</a></p>



<a name="229554996"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229554996" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229554996">(Mar 09 2021 at 21:13)</a>:</h4>
<p>Thanks! Reviewed and responded.</p>



<a name="229641382"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/219381-t-libs/topic/environment%2C%20locking%2C%20fork%2C%20and%20Command/near/229641382" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> hyd-dev <a href="https://rust-lang.github.io/zulip_archive/stream/219381-t-libs/topic/environment.2C.20locking.2C.20fork.2C.20and.20Command.html#229641382">(Mar 10 2021 at 11:32)</a>:</h4>
<p>The 3rd (and maybe also 4th) points seem exactly what <a href="https://github.com/rust-lang/rust/issues/55359">#55359</a> <a href="https://github.com/rust-lang/rust/issues/64718#issuecomment-692158468">did</a>.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>